/*
Copyright (C) 2015 Pieter Staal

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "waterGenerator.h"
#include <iostream>
#include <SFML/Graphics.hpp>
#include "River.h"

#define NORTH x + (y-1) * settings.size
#define EAST  (x+1) + y * settings.size
#define SOUTH x + (y-1) * settings.size
#define WEST  (x-1) + y * settings.size

using namespace sf;

// Temporary random function for testing
int randint(int low, int high);

WaterGenerator::WaterGenerator(WaterSettings _settings)
{
    settings = _settings;
    watermap = new double[(int)((settings.size / riverCoordMod) * (settings.size / riverCoordMod))];
    heightmap = settings.heightmap;
    normalizedHeightmap = new double[settings.size * settings.size];
    displayWatermap = new double[settings.size * settings.size];
    waterLevel = settings.waterLevel;
    landmap = settings.landmap;

    for (int i = 0; i < (int)((settings.size / riverCoordMod) * (settings.size / riverCoordMod)); i++)
    {
        watermap[i] = 0;
    }

}

void WaterGenerator::updateWaterMap(int iterations)
{
    for (int i = 0; i < iterations; i++)
    {
        for (int r = 0; r < rivers.size(); r++)
        {
            //std::cout << "updating river " << r << ".\n";
            rivers.at(r).flow();
        }
    }
}

void WaterGenerator::addRiver()
{
    std::cout << "Adding river...\n";
    determineCoasts();

    RiverSettings riverSettings;
    riverSettings.watermap = watermap;
    riverSettings.normalizedHeightmap = normalizedHeightmap;
    riverSettings.displayWatermap = displayWatermap;
    riverSettings.mapSize = settings.size;
    riverSettings.riverCoordMod = riverCoordMod;

    //riverSettings.position = Vector2i(randint(0, settings.size - 1) / riverCoordMod, randint(0, settings.size - 1) / riverCoordMod);

    int posIndex = randint(0, coastIndices.size() - 1);

    Vector2i riverPos;
    riverPos.x = (coastIndices.at(posIndex) % settings.size) / riverCoordMod;
    riverPos.y = (coastIndices.at(posIndex) / settings.size) / riverCoordMod;

    riverSettings.position = riverPos;

    rivers.push_back(River(riverSettings));
}

void WaterGenerator::normalizeMap()
{
    double min = heightmap[0], max = heightmap[0];
    for (int i = 0; i < settings.size * settings.size; i++) {
        min = std::min(min, heightmap[i]);
        max = std::max(max, heightmap[i]);
    }
    for (int i = 0; i < settings.size * settings.size; i++)
        normalizedHeightmap[i] = (heightmap[i] - min)
	    / (max - min);
}

void WaterGenerator::determineCoasts()
{
    coastIndices.clear();
    for (int x = 1; x < settings.size - 1; x++)
    {
        for (int y = 1; y < settings.size - 1; y++)
        {
            if (normalizedHeightmap[x + y * settings.size] > waterLevel)
            {
                bool north = landmap[x + (y-1) * settings.size];// < waterLevel;
                bool east = landmap[(x+1) + y * settings.size];// < waterLevel;
                bool south = landmap[x + (y+1) * settings.size];// < waterLevel;
                bool west = landmap[(x-1) + y * settings.size];// < waterLevel;

                if (!(north || east || south || west))
                {
                    coastIndices.push_back(x + y * settings.size);
                }
            }
        }
    }
}

// Needed a quick randomization function for testing
// This random function should be improved in the future
int randint(int low, int high)
{
    int value = rand() % (high + 1 - low) + low;
    srand(value * rand());

    return value;
}
